
export default class Utils {

    /**
    * 计算缩放
    * @param base 基础值
    * @param max 最大值
    * @param arr 缩放列表
    * @returns 
    */
    static lerpScale(base: number, max: number, ...arr: number[]) {
        for (let elm of arr) {
            base = base * elm / max;
        }
        return Math.min(max, base);
    }

    /**
     * 数学sin cos ...
     */
    private static mathSinCos(attr, angle: number): number {
        return Math[attr](angle * Math.PI / 180);
    }

    /**
     * sin
     * @param angle 角度，0~360
     */
    public static sin(angle: number): number {
        return this.mathSinCos('sin', angle);
    }

    /**
     * cos
     * @param angle 角度，0~360
     */
    public static cos(angle: number): number {
        return angle % 180 == 90 ? 0 : this.mathSinCos('cos', angle);
    }

    static random() {
        return Math.random();
    }

    static randomInt(min: number, max: number) {
        return Math.floor(this.random() * (max - min + 1)) + min
    }

    static randomFlot(min: number, max: number) {
        return this.random() * (max - min) + min;
    }

    static apply(obj: any, key: PropertyKey, argumentsList: any[] = []) {
        let target = Reflect.get(obj, key);
        target && typeof target === "function" && Reflect.apply(target, obj, argumentsList);
    }

    static distances(x1: number, y1: number, x2: number, y2: number) {

        return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
    }

    /**
    * 取数组的随机值
    * @param array 数组
    * @param item 子项，存在时则随机出来的值不为item的值，若长度小于等于1，则无效
    */
    static randomInArray<T>(array: T[], item?: T | ((o: T) => boolean)): T {
        let len = array.length, splice = len;
        if (len > 1 && !Utils.isNil(item)) {

            let index = typeof item === "function" ? array.findIndex(<any>item) : array.indexOf(item);

            if (index > -1) {
                len--;
                splice = index;
            }
        }

        let rndIdx = this.randomInt(0, len);
        if (rndIdx >= splice) {
            ++rndIdx;
        }

        return array[rndIdx];
    }


    static overlap(arr1: any[], arr2: any[]) {
        for (let elm of arr1) {
            if (arr2.some(v => v === elm)) {
                return true;
            }
        }

        return false;
    }


    static isUndefined(target) {
        return typeof target === "undefined";
    }

    static isNil(target: any) {
        return target === void 0 || target === null;
    }

    static generateUniqId(len: number): string {
        let chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        let uuid: string[] = [];
        for (let i = 0; i < len; i++) {
            uuid.push(chars[0 | Math.random() * chars.length]);
        }
        return uuid.join("");
    }

    static encodeURIParam(param: any): string {
        let strs = [];
        for (let key in param) {
            strs.push(key + "=" + encodeURIComponent(param[key]));
        }
        return strs.join("&");
    }

    static GUID = (function () {
        let gid = 0;
        return function () {
            return ++gid
        }
    }())

    static getGUIDByObject(obj: any): number {
        let v = Reflect.getOwnPropertyDescriptor(obj, "$__GID");
        if (!v || this.isNil(v.value)) {
            let num = this.GUID();
            Reflect.defineProperty(obj, "$__GID", {
                enumerable: true,
                writable: false,
                configurable: false,
                value: num
            })

            return num;
        }

        return v.value;
    }


    static parseNum(str: any) {
        let num = Number(str);
        if (isNaN(num)) return 0;

        return num;
    }


    static formatString(str: string, ...data: string[]) {
        if (data == null) {
            return "";
        }

        for (let i = 0; i < data.length; i++) {
            str = str.replace(/{[0-9]}|{[1-9][0-9]}|%s|%d/i, data[i]);
        }

        return str
    }

    /**
     * 末尾补齐
     * @param num 
     * @param len 
     * @param sign 
     * @returns 
     */
    static padStart(num: number, len: number = 2, sign: string = "0") {
        let str = num.toString(), size = str.length;
        if (size >= len) {
            return str.substring(0, len);
        }

        return this.getSing(sign, len - size) + str;

    }

    /**
     * 首位补齐
     * @param num 
     * @param len 
     * @param sign 
     * @returns 
     */
    static padEnd(num: number, len: number = 2, sign: string = "0") {
        let str = num.toString(), size = str.length;
        if (size >= len) {
            return str.substring(0, len);
        }

        return str + this.getSing(sign, len - size);
    }

    static getSing(sing: string, num: number) {
        let strs = [];
        for (let i = 0; i < num; i++) {
            strs.push(sing);
        }

        return strs.join();
    }


    static equal(obj1: object, obj2: object, key: string) {

        return obj1[key] === obj2[key];
    }


    /**
     * 数组去重，会重新排序
     * @param arr 
     * @returns 
     */
    static unique<T>(arr: T[]) {
        arr.sort();
        let arrry = [arr[0]];

        for (let i = 1; i < arr.length; i++) {
            if (arr[i] !== arr[i - 1]) {
                arrry.push(arr[i]);
            }
        }
        return arrry;
    }

    /**
     * 数组去重(不排序)
     * @param arr 
     * @returns 
     */
    static uniqueUnSort<T>(arr: T[]) {
        let array = [];
        for (let i = 0; i < arr.length; i++) {
            if (array.indexOf(arr[i]) !== -1) {
                array.push(arr[i]);
            }
        }

        return array;
    }
}